Skip to content

fix(query-core): restore NoInfer on persister's TQueryKey#10601

Open
neefrehman wants to merge 2 commits intoTanStack:mainfrom
neefrehman:fix/persister-query-key-noinfer
Open

fix(query-core): restore NoInfer on persister's TQueryKey#10601
neefrehman wants to merge 2 commits intoTanStack:mainfrom
neefrehman:fix/persister-query-key-noinfer

Conversation

@neefrehman
Copy link
Copy Markdown
Contributor

@neefrehman neefrehman commented Apr 27, 2026

Summary

Follow-up to #10510. That PR removed NoInfer from all three persister generics to fix TQueryFnData inference when the companion queryFn declares a parameter (#7842). This restores NoInfer<TQueryKey> only — keeping #10510's benefit while preventing the persister slot from widening TQueryKey inference.

Fixes #10600.

The interaction

Without NoInfer on TQueryKey, the persister slot contributes to TQueryKey inference. When Register.queryKey is augmented to a narrowed constraint (as documented and introduced in #8521), TQueryKey widens to that constraint instead of the literal passed to queryKey. Wrappers whose return type brands the key with DataTag<TQueryKey, ...> (which is required to support type-safety when using options with e.g. getQueryData) then produce a brand on the wider type, and a plain literal tuple can no longer satisfy both the augmented constraint and the phantom brand.

See #10600 for the minimal repro (a ~15-line wrapper + augmented Register.queryKey + a typed variable assignment reproduces TS2322 on 5.100.5 and compiles cleanly on 5.100.1).

Why this fix is safe

A note on regression testing

I tried to add a .test-d.tsx that augments Register.queryKey and asserts a DataTag-branded wrapper return accepts literal queryKeys. It caught the bug, but declare module '@tanstack/query-core' is global — the augmentation leaked into every sibling .test-d.tsx and produced ~30 spurious TS2322s across useQuery, useSuspenseQuery, etc. (all of which use literal string[] keys that don't satisfy the narrowed constraint).

More broadly, I didn't find any existing tests for the Register augmentations (defaultError, queryMeta, mutationMeta, queryKey, mutationKey) — by construction each would need its own isolated compilation unit. Flagging it in case the maintainers want to set that up separately; I've left it out of this PR to keep the scope minimal.

Test plan

  • packages/query-corepnpm run test:types (TS 5.4 – 6.0): pass
  • packages/react-querypnpm run test:types (TS 5.4 – 6.0): pass
  • packages/query-core — vitest: 526 pass / 0 fail
  • packages/react-query — vitest: 540 pass / 0 fail

Summary by CodeRabbit

  • Bug Fixes
    • Resolved a type checking issue with the query persister option that prevented proper configuration in certain advanced scenarios.

Follow-up to TanStack#10510. That PR removed NoInfer from all three persister
generics to fix TQueryFnData inference when the companion queryFn
declares a parameter (TanStack#7842). Keeping NoInfer on TQueryKey preserves
that fix while preventing the persister slot from widening TQueryKey
inference.

Without NoInfer on TQueryKey, the persister slot contributes to
TQueryKey inference. When Register.queryKey is augmented to a narrowed
constraint, TQueryKey widens to that constraint instead of the literal
passed to queryKey. Wrappers that brand their return with
DataTag<TQueryKey, ...> then produce a brand on the wider type, which
a plain literal tuple can no longer satisfy in contravariant positions
(vi.mocked(...).mockReturnValue, typed variable assignments, etc.).

TQueryFnData still participates in inference, so TanStack#10510's positive and
negative type tests continue to pass.
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 27, 2026

📝 Walkthrough

Walkthrough

This pull request applies a surgical TypeScript type inference fix to the persister option in QueryOptions. The change wraps TQueryKey in NoInfer to prevent the contravariant persister slot from influencing TQueryKey inference, resolving assignability issues for users combining Register.queryKey augmentation with DataTag-branded wrapper return types.

Changes

Cohort / File(s) Summary
Type Inference Fix
packages/query-core/src/types.ts
Modified persister property type to use NoInfer<TQueryKey> instead of bare TQueryKey, preventing the persister slot from participating in TQueryKey inference while preserving TQueryFnData inference benefits.
Changeset Documentation
.changeset/fix-persister-query-key-infer.md
Added changeset metadata describing the patch-level type inference adjustment for the persister generic parameter.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~5 minutes

Poem

🐰 A hop, a skip, and types align,
NoInfer guards the persister line,
DataTag's brand now safe and sound,
Where narrowed Register keys are found!
One small tweak, a rabbit's delight,
Inference flows, all types are right!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: restoring NoInfer wrapper on persister's TQueryKey generic parameter to fix type inference issues.
Description check ✅ Passed The description comprehensively explains the change, its motivation, the interaction with Register augmentation, testing performed, and explicitly addresses why a regression test wasn't included. All critical information is present and well-organized.
Linked Issues check ✅ Passed The PR directly addresses issue #10600 by implementing the suggested structural tweak: wrapping TQueryKey in NoInfer within the persister generic. The change preserves the TQueryFnData inference fix from #10510 while resolving the DataTag branding issue.
Out of Scope Changes check ✅ Passed All changes are narrowly scoped to the stated objective: a Changeset entry and a single-line type signature modification adding NoInfer to persister. No extraneous modifications are present.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@nx-cloud
Copy link
Copy Markdown

nx-cloud Bot commented Apr 27, 2026

View your CI Pipeline Execution ↗ for commit 11e5b6a

Command Status Duration Result
nx affected --targets=test:sherif,test:knip,tes... ✅ Succeeded 1m 12s View ↗
nx run-many --target=build --exclude=examples/*... ✅ Succeeded 1s View ↗

☁️ Nx Cloud last updated this comment at 2026-04-28 15:52:49 UTC

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
packages/query-core/src/types.ts (1)

249-249: Add a focused d.ts regression test for this inference path.

Non-blocking: the type change looks correct, but this exact Register.queryKey-augmentation + DataTag + persister interaction previously regressed and should be pinned with an isolated type test to prevent reintroduction.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/query-core/src/types.ts` at line 249, Add a focused TypeScript
declaration test that pins the inference path involving the persister property
and its generics: create a .d.ts or .test-d.ts that reproduces the
Register.queryKey augmentation combined with a DataTag and a persister: ensure
the persister is typed as QueryPersister<TQueryFnData, NoInfer<TQueryKey>,
TPageParam> and assert the inferred types (using type assertions or expect-type
utilities) for the resulting query registration so the previously regressed
interaction is covered and will fail if inference changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@packages/query-core/src/types.ts`:
- Line 249: Add a focused TypeScript declaration test that pins the inference
path involving the persister property and its generics: create a .d.ts or
.test-d.ts that reproduces the Register.queryKey augmentation combined with a
DataTag and a persister: ensure the persister is typed as
QueryPersister<TQueryFnData, NoInfer<TQueryKey>, TPageParam> and assert the
inferred types (using type assertions or expect-type utilities) for the
resulting query registration so the previously regressed interaction is covered
and will fail if inference changes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 993261ce-7bfd-48c9-bd0d-b4dd4fb44e5c

📥 Commits

Reviewing files that changed from the base of the PR and between dd901ae and 5f82c4d.

📒 Files selected for processing (2)
  • .changeset/fix-persister-query-key-infer.md
  • packages/query-core/src/types.ts

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Apr 28, 2026

More templates

@tanstack/angular-query-experimental

npm i https://pkg.pr.new/@tanstack/angular-query-experimental@10601

@tanstack/eslint-plugin-query

npm i https://pkg.pr.new/@tanstack/eslint-plugin-query@10601

@tanstack/preact-query

npm i https://pkg.pr.new/@tanstack/preact-query@10601

@tanstack/preact-query-devtools

npm i https://pkg.pr.new/@tanstack/preact-query-devtools@10601

@tanstack/preact-query-persist-client

npm i https://pkg.pr.new/@tanstack/preact-query-persist-client@10601

@tanstack/query-async-storage-persister

npm i https://pkg.pr.new/@tanstack/query-async-storage-persister@10601

@tanstack/query-broadcast-client-experimental

npm i https://pkg.pr.new/@tanstack/query-broadcast-client-experimental@10601

@tanstack/query-core

npm i https://pkg.pr.new/@tanstack/query-core@10601

@tanstack/query-devtools

npm i https://pkg.pr.new/@tanstack/query-devtools@10601

@tanstack/query-persist-client-core

npm i https://pkg.pr.new/@tanstack/query-persist-client-core@10601

@tanstack/query-sync-storage-persister

npm i https://pkg.pr.new/@tanstack/query-sync-storage-persister@10601

@tanstack/react-query

npm i https://pkg.pr.new/@tanstack/react-query@10601

@tanstack/react-query-devtools

npm i https://pkg.pr.new/@tanstack/react-query-devtools@10601

@tanstack/react-query-next-experimental

npm i https://pkg.pr.new/@tanstack/react-query-next-experimental@10601

@tanstack/react-query-persist-client

npm i https://pkg.pr.new/@tanstack/react-query-persist-client@10601

@tanstack/solid-query

npm i https://pkg.pr.new/@tanstack/solid-query@10601

@tanstack/solid-query-devtools

npm i https://pkg.pr.new/@tanstack/solid-query-devtools@10601

@tanstack/solid-query-persist-client

npm i https://pkg.pr.new/@tanstack/solid-query-persist-client@10601

@tanstack/svelte-query

npm i https://pkg.pr.new/@tanstack/svelte-query@10601

@tanstack/svelte-query-devtools

npm i https://pkg.pr.new/@tanstack/svelte-query-devtools@10601

@tanstack/svelte-query-persist-client

npm i https://pkg.pr.new/@tanstack/svelte-query-persist-client@10601

@tanstack/vue-query

npm i https://pkg.pr.new/@tanstack/vue-query@10601

@tanstack/vue-query-devtools

npm i https://pkg.pr.new/@tanstack/vue-query-devtools@10601

commit: 11e5b6a

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

persister slot drags TQueryKey into inference, breaking Register.queryKey + DataTag consumers

2 participants